package caches

import (
	gocache "github.com/patrickmn/go-cache"
	"time"
)

type MemoryStore struct {
	cache   *gocache.Cache
	expired time.Duration
}

func NewMemoryStore(expired time.Duration) *MemoryStore {
	return &MemoryStore{
		expired: expired,
		cache:   gocache.New(expired, expired),
	}
}

func (store *MemoryStore) Get(key string) (string, bool, error) {
	d, exist := store.cache.Get(key)
	if !exist {
		return "", exist, nil
	}
	return d.(string), exist, nil
}

func (store *MemoryStore) TTL(key string) (time.Duration, error) {
	_, exp, exist := store.cache.GetWithExpiration(key)
	if !exist {
		return -1, nil
	}

	return time.Now().Sub(exp), nil
}

func (store *MemoryStore) Inc(k string, n int64) error {
	return store.cache.Increment(k, n)
}

func (store *MemoryStore) Dec(k string, n int64) error {
	return store.cache.Decrement(k, n)
}

func (store *MemoryStore) Exist(k string) (bool, error) {
	_, find := store.cache.Get(k)
	return find, nil
}

func (store *MemoryStore) Delete(key string) error {
	store.cache.Delete(key)
	return nil
}

func (store *MemoryStore) GetSet(key string, value string, expired time.Duration) (string, error) {
	return store.GetSetFunc(key, func() string {
		return value
	}, expired)
}

func (store *MemoryStore) GetSetFunc(key string, f func() string, expired time.Duration) (string, error) {
	d, exist, err := store.Get(key)
	if err != nil {
		return "", err
	}
	if !exist {
		tmp := f()
		store.Set(key, tmp)

		d = tmp
	}
	return d, nil
}

func (store *MemoryStore) Set(key string, value string) error {
	return store.SetExpire(key, value, store.expired)
}

func (store *MemoryStore) SetExpire(key string, value string, expired time.Duration) error {
	store.cache.Set(key, value, expired)
	return nil
}

// Keys 返回所有缓存key
func (store *MemoryStore) Keys() ([]string, error) {
	d := store.cache.Items()
	var keys []string
	for k, _ := range d {
		keys = append(keys, k)
	}
	return keys, nil
}

func (store *MemoryStore) SetKeyPrefix(prefix string) {
	return
}
